package br.unifor.Tads.Lista;

import br.unifor.Exceptions.ChaveInvalidaException;
import br.unifor.Exceptions.ListaVaziaException;

/**
 * Created with IntelliJ IDEA.
 * Autor: Valmar Júnior
 * Date: 20/09/13
 * Time: 09:54
 */
public class ListaEncadeada {

    private int tamanho;
    private Node primeiro;
    private Node posicao;
    private Node ultimo;

    public ListaEncadeada() {
        this.tamanho = 0;
        this.primeiro = new Node();
        this.posicao = this.primeiro;
        this.ultimo = this.primeiro;
        this.primeiro.setProximo(null);
    }

    public boolean estaVazia() {
        if (this.tamanho == 0)
            return true;
        return false;
    }

    public int qteElementos() {
        return this.tamanho;
    }

    public Object pesquisa(Object chave) throws ListaVaziaException, ChaveInvalidaException {
        if (estaVazia())
            throw new ListaVaziaException("ERRO: Lista Vazia");
        if (chave == null)
            throw new ChaveInvalidaException("ERRO: Chave Inválida");
        Node auxiliar = this.primeiro;
        int contador = 0;
        while (auxiliar.getProximo() != null) {
            if (auxiliar.getProximo().getObjeto().equals(chave))
                return auxiliar.getProximo().getObjeto();
            else
                contador++;
            auxiliar = auxiliar.getProximo();

        }
        if (contador == this.tamanho)
            System.err.println("ERRO: Valor " + chave + " encontrado!");
        return null;
    }

    public void insereObjeto(Object objeto) {
        this.ultimo.setProximo(new Node());
        this.ultimo = this.ultimo.getProximo();
        this.ultimo.setObjeto(objeto);
        this.ultimo.setProximo(null);
        tamanho++;
    }

    public Object removerObjeto(Object chave) throws ListaVaziaException, ChaveInvalidaException {
        if (estaVazia())
            throw new ListaVaziaException("ERRO: Lista Vazia");
        if (chave == null)
            throw new ChaveInvalidaException("ERRO: Chave Inválida");
        Node auxiliar = this.primeiro;
        while (auxiliar.getProximo() != null && !auxiliar.getProximo().getObjeto().equals(chave)) {
            auxiliar = auxiliar.getProximo();
        }
        if (auxiliar.getProximo() == null)
            return null;
        Node q = auxiliar.getProximo();
        Object objeto = q.getObjeto();
        auxiliar.setProximo(q.getProximo());
        if (auxiliar.getProximo() == null)
            this.ultimo = auxiliar;
        tamanho--;
        return objeto;
    }

    public Object retiraPrimeiroPosicao() throws ListaVaziaException {
        if (estaVazia())
            throw new ListaVaziaException("ERRO: Lista Vazia");
        Node auxiliar = this.primeiro;
        Object objeto = this.primeiro.getObjeto();
        this.primeiro = this.primeiro.getProximo();
        auxiliar.setProximo(null);
        this.tamanho--;
        return objeto;

    }

    public Object primeiroNaLista() {
        this.posicao = primeiro;
        return proximo();
    }

    public Object proximo() {
        this.posicao = this.posicao.getProximo();
        if (this.posicao == null)
            return null;
        else
            return this.posicao.getObjeto();
    }

    public void imprime() {
        Node auxiliar = this.primeiro.getProximo();
        while (auxiliar != null) {
            System.out.println(auxiliar.getObjeto().toString());
            auxiliar = auxiliar.getProximo();
        }
    }
}
